﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using LayerData;
using LayerData.Persona ;
using LayerEntity.Persona;
using LayerEntity.Persona.RecursosHumanos;
using LayerEntity.Sistema;

namespace LayerLogic.Persona
{
    /// <summary>
    /// Descripcion: 
    /// Clase que permite la administracion de Clientes, Proveedores, Empleados y Otros.
    /// </summary>
    public class LPersona
    {
        #region Variables
        List<IEPersona> cli = new List<IEPersona>();
        List<IEPersona> prov = new List<IEPersona>();
        List<IEPersona> empl = new List<IEPersona>();
        readonly List<ESexo> sexo = new List<ESexo>();
        List<ETipoCuentaCorriente> tipocte = new List<ETipoCuentaCorriente>();
        public delegate void AddObject(string msj, EnumOperaciones op);
        public event AddObject UpdateList = delegate { };

        private readonly MantenimientoPersona manPer;
        #endregion

        #region Constructor
        /// <summary>
        /// Inicializa la clase <see cref="LPersona"/>
        /// </summary>
        public LPersona(IPostgreSqlConnectionInfo con)
        {
            this.cli = new List<IEPersona>();
            this.prov = new List<IEPersona>();
            this.empl = new List<IEPersona>();
            this.CurrentConnection = con;
            this.manPer = new MantenimientoPersona(this.CurrentConnection);
        }

        public LPersona()
        {
            this.cli = new List<IEPersona>();
            this.prov = new List<IEPersona>();
            this.empl = new List<IEPersona>();
            this.CurrentConnection = ObjectFactory.CreateConnectionInfo();
            this.manPer = new MantenimientoPersona(this.CurrentConnection);
        }

        #endregion

        #region Metodos

        public void AddCliente(IEPersona cliente)
        {
            if (this.cli == null)
            {
                this.cli = new List<IEPersona>();
            }
            if (cliente != null)
            {
                int index = this.cli.FindIndex(delegate(IEPersona cl)
                {
                    return cl.IdPersona == cliente.IdPersona;
                });
                if (index < 0)
                {
                    this.cli.Add(cliente);
                }
                else
                {
                    this.cli[index] = cliente;
                }
                this.UpdateList("Cliente Agregado", EnumOperaciones.AddCollection);
            }
        }

        public void AddEmpleado(IEPersona empleado)
        {
            if (this.empl == null)
            {
                this.empl = new List<IEPersona>();
            }
            if (empleado != null)
            {
                int index = this.empl.FindIndex(delegate(IEPersona em)
                {
                    return em.IdPersona == empleado.IdPersona;
                });
                if (index < 0)
                {
                    this.empl.Add(empleado);
                }
                else
                {
                    this.empl[index] = empleado;
                }
                this.UpdateList("Empleado Agregado", EnumOperaciones.AddCollection);
            }
        }

        public void AddProveedor(IEPersona proveedor)
        {
            if (this.prov == null)
            {
                this.prov = new List<IEPersona>();
            }
            if (proveedor != null)
            {
                int index = this.prov.FindIndex(delegate(IEPersona p)
                {
                    return p.IdPersona == proveedor.IdPersona;
                });
                if (index < 0)
                {
                    this.prov.Add(proveedor);
                }
                else
                {
                    this.prov[index] = proveedor;
                }

                this.UpdateList("Proveedor Agregado", EnumOperaciones.AddCollection);
            }
        }

        /// <summary>
        /// Este metodo solo carga los 200 Ultimos registros.
        /// </summary>
        ///<param name="loadAll">Permite cargar todos los clientes registrados</param>
        private void LoadClientes(int limite)
        {
            if (this.cli == null)
            {
                this.cli = new List<IEPersona>();
            }
            if (limite == 0) {
                this.cli = this.manPer.GetClientes(0);
            }
            if (this.cli.Count == 0)
            {
                this.cli = this.manPer.GetClientes(limite);
            }
        }
       
        private void LoadProveedor(int limit)
        {
            if (this.prov == null)
            {
                this.prov = new List<IEPersona>();
            }
            if (limit == 0) {
                this.prov = this.manPer.GetProveedores(0);
            }
            if (this.prov.Count == 0)
            {
                this.prov = this.manPer.GetProveedores(limit);
            }
        }

        private void LoadEmpleados(int limit)
        { 
            if (this.empl == null)
            {
                this.empl = new List<IEPersona>();
            }
            if(limit ==0){
                this.empl = this.manPer.GetEmpleados(0);
            }
            
            if (this.empl.Count == 0)
            {
                this.empl = this.manPer.GetEmpleados(limit);
            }
        }

        #endregion

        #region Funciones

        public List<EContacto> GetContactos(string patern)
        {
            return this.manPer.GetContactos(patern);
        }

        public List<ParamsToSearch> GetValues(EnumTipoPersona tipo)
        {
            List<ParamsToSearch> lista = new List<ParamsToSearch>();
            //codigo,raz,nombre,comercial y nro de documento

            lista.Add(new ParamsToSearch("id_persona", "Codigo"));
            lista.Add(new ParamsToSearch("rs_persona", "Razon Social"));
            lista.Add(new ParamsToSearch("nom_com_persona", "Nombre Comercial"));
            lista.Add(new ParamsToSearch("doc_persona", "Numero de Documento"));
            if (tipo == EnumTipoPersona.Empleado)
            {
                lista.Add(new ParamsToSearch("nom_persona", "Nombres"));
                lista.Add(new ParamsToSearch("ape_persona", "Apellidos"));
            }
            return lista;
        }

        public List<IEPersona> GetProveedores(int limite)
        {
            this.LoadProveedor(limite );
            return this.prov;
        }

        public List<IEPersona> GetProveedores(int limit, string condition)
        {
            return this.manPer.GetProveedores(limit, condition);
        }

        public List<IEPersona> GetClient()
        {
            return this.cli;
        }

        public List<IEPersona> GetProveedores()
        {
            return this.prov;
        }

        public List<IEPersona> GetClient( int limite)
        {
            this.LoadClientes(limite);
            return this.cli;
        }

        public List<IEPersona> GetClient(int limit, string condition)
        {
            return this.manPer.GetClientes(limit, condition);
        }

        public IEPersona GetClient(IEPersona c)
        {
            return this.cli.Find(delegate(IEPersona cl)
            {
                return cl.IdPersona == c.IdPersona;
            });
        }
        
        public List<IEPersona> GetClient(string descripcion, string fielName)
        {
            List<IEPersona> res = new List<IEPersona>();
            descripcion = descripcion.Trim().ToUpper();
            res = this.cli.FindAll(delegate(IEPersona c)
            {
                bool resSearch = false;
                switch ( fielName )
                {
                    case "id_persona":
                        resSearch = c.IdPersona.ToUpper().Contains(descripcion);
                        break;
                    case "rs_persona":
                        resSearch = c.RazonSocial.ToUpper().Contains(descripcion);
                        break;
                    case "nom_com_persona":
                        resSearch = c.NombreComercial.ToUpper().Contains(descripcion);
                        break;
                    case "doc_persona":
                        resSearch = c.NumeroDocumento.ToUpper().Contains(descripcion);
                        break;
                    case "nom_persona":
                        resSearch = c.Nombres.ToUpper().Contains(descripcion);
                        break;
                    case "ape_persona":
                        resSearch = c.Nombres.ToUpper().Contains(descripcion);
                        break;
                    default:
                        break;
                }
                return resSearch;
            });

            return res;
        }

        public List<IEPersona> GetEmpleados(int limite)
        {
            this.LoadEmpleados(limite);
            return this.empl;
        }

        public List<IEPersona> GetEmployee()
        {
            return this.empl;
        }

        public IEPersona GetEmployee(string id)
        {
            IEPersona emp = ObjectFactoryPersona.CreateEmployee();
            if (this.empl != null)
            {
                emp = this.empl.Find(delegate(IEPersona e)
                {
                    return e.IdPersona.Trim() == id.Trim();
                });
            }
            return emp;
        }

        public IEPersona GetSupplier(IEPersona p)
        {
            return this.prov.Find(delegate(IEPersona pr)
            {
                return pr.IdPersona == p.IdPersona;
            });
        }

        public List<IEPersona> GetSupplier(string descripcion)
        {
            return this.prov.FindAll(delegate(IEPersona pr)
            {
                if (pr.RazonSocial.ToUpper().Trim().Contains(descripcion.ToUpper().Trim()))
                {
                    return true;
                }
                else if (pr.NombreComercial.ToUpper().Trim().Contains(descripcion.ToUpper().Trim()))
                {
                    return true;
                }
                else
                {
                    return false;
                }
            });
        }
        public IEPersona GetSupplier(string numdoc,bool only)
        {
            IEPersona per = prov.Find(delegate(IEPersona p) {
                return p.NumeroDocumento == numdoc;
            });

            if (per == null) {
                per = ObjectFactoryPersona.CreateSupplier();
            }
            return per;
        }
        /// <summary>
        /// Retorna una Lista con los Sexos Disponibles.
        /// </summary>
        /// <returns></returns>
        public List<ESexo> GetSexos()
        {
            if (this.sexo.Count == 0)
            {
                this.sexo.Add(new ESexo(1, "Femenino"));
                this.sexo.Add(new ESexo(2, "Masculino"));
            }
            return this.sexo;
        }

        public ESexo GetSexos(int id)
        {
            this.GetSexos();
            return this.sexo.Find(delegate(ESexo s)
            {
                return s.IdSexo == id;
            });
        }

        public List<ETipoCuentaCorriente> GetTipoCuentaCorriente()
        {
            if (this.tipocte.Count == 0)
            {
                this.tipocte = this.manPer.GetTipoCuentaCorriente();
            }
            return this.tipocte;
        }

        public ETipoCuentaCorriente GetTipoCuentaCorriente(int id)
        {
            if (this.tipocte.Count == 0)
            {
                this.tipocte = this.manPer.GetTipoCuentaCorriente();
            }

            return this.tipocte.Find(delegate(ETipoCuentaCorriente cc)
            {
                return cc.IdTipoCtaCte == id;
            });
        }

        public DataTable GetListaClientes(ESistema obj)
        {
            return this.manPer.GetListaClientes(obj);
        }

        #endregion

        #region Funciones de Mantenimiento
        public string SaveClientes(IEPersona cli, EnumOperaciones op)
        {
            return this.manPer.SaveCliente(cli, (LayerData.EnumOperaciones)(int)op);
        }

        public int SaveAddress(EDireccion address, EnumOperaciones op)
        {
            return this.manPer.SaveAddress(address, (LayerData.EnumOperaciones)(int)op);
        }

        public string SaveProveedores(IEPersona prov, EnumOperaciones op)
        {
            return this.manPer.SaveProveedor(prov, (LayerData.EnumOperaciones)(int)op);
        }

        public string SaveEmpleado(IEPersona emp, EnumOperaciones op)
        {
            return this.manPer.SaveEmpleado(emp, (LayerData.EnumOperaciones)(int)op);
        }

        public int SaveAccount(ECuentasCorrientes cte, EnumOperaciones op)
        {
            return this.manPer.SaveAcount(cte, (LayerData.EnumOperaciones)(int)op);
        }

        public int SavePlanilla(EPlanilla plan)
        {
            return this.manPer.SavePlanilla(plan);
        }

        public int SaveContact(EContacto c, EnumOperaciones op)
        {
            return this.manPer.SaveContact(c, (LayerData.EnumOperaciones)(int)op);
        }

        public int SaveContactRelation(EContacto c, EnumOperaciones op)
        {
            return this.manPer.SaveContactRelation(c, (LayerData.EnumOperaciones)(int)op);
        }

        #endregion

        #region Propiedades

        public IPostgreSqlConnectionInfo CurrentConnection { get; set; }
        #endregion
    }
}